package cn.xinfei.xdecision.manager.controller.component.decisiontree;


import cn.xinfei.xdecision.common.model.common.PageResult;
import cn.xinfei.xdecision.common.model.common.ResponseEntityBuilder;
import cn.xinfei.xdecision.common.model.common.ResponseEntityDto;
import cn.xinfei.xdecision.common.model.common.requestParam.AssemblyRuleCodeReq;
import cn.xinfei.xdecision.common.model.component.decisiontree.DecisionTreeVersion;
import cn.xinfei.xdecision.common.model.component.decisiontree.vo.DecisionTreeVersionListVo;
import cn.xinfei.xdecision.common.model.component.decisiontree.vo.DecisionTreeVersionVo;
import cn.xinfei.xdecision.common.service.component.decisiontree.DecisionTreeVersionService;
import cn.xinfei.xdecision.common.utils.constant.OperateNameConst;
import cn.xinfei.xdecision.common.utils.constant.OperateTypeEnum;
import cn.xinfei.xdecision.common.utils.constant.RedisConstant;
import cn.xinfei.xdecision.common.utils.exception.ApiException;
import cn.xinfei.xdecision.common.utils.exception.enums.ErrorCodeEnum;
import cn.xinfei.xdecision.manager.web.aop.ArchivesLog;
import com.baomidou.mybatisplus.extension.api.ApiController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.text.MessageFormat;
import java.util.List;

/**
 * 决策树版本controller
 */
@Api(tags = "组件中心-决策树")
@RestController
@RequestMapping("/v3/decisionTree/version")
@Slf4j
public class DecisionTreeVersionController extends ApiController {

    @Resource
    private DecisionTreeVersionService versionService;

    @Resource
    private RedissonClient redissonClient;

    @ApiOperation(value = "决策树_查询的版本详情")
    @PostMapping("/getVersionInfo/{versionId}")
    public ResponseEntityDto<DecisionTreeVersionVo> getVersionInfo(@PathVariable Long versionId) {
        return ResponseEntityBuilder.buildNormalResponse(versionService.queryById(versionId));
    }

    @ApiOperation(value = "决策树_新建版本")
    @PostMapping("/addVersion")
    @ArchivesLog(type = OperateTypeEnum.CREATE,name = OperateNameConst.ComponentOpt.SAVE_VERSION)
    public ResponseEntityDto<Long> addVersion(@RequestBody DecisionTreeVersionVo version) {
        if (StringUtils.isEmpty(version.getDecisionTreeCode())) {
            return ResponseEntityBuilder.buildErrorResponse(ErrorCodeEnum.DECISION_CODE_CAN_NOT_NULL);
        }
        //获取分布式锁
        String key = MessageFormat.format(RedisConstant.RISK_ENGINE_BASIC_INFO_KEY,
                RedisConstant.COMPONENT_KEY,
                RedisConstant.DECISION_TABLE,
                version.getDecisionTreeCode());
        RLock lock = redissonClient.getLock(key);
        if (!lock.tryLock()) {
            return ResponseEntityBuilder.buildErrorResponse(ErrorCodeEnum.RECEIPT_CONCURRENT_OPERATE_ERROR);
        }
        try {
            return ResponseEntityDto.success(versionService.checkAndAddVersion(version));
        } catch (ApiException e) {
            log.error("新建版本业务异常", e);
            return ResponseEntityBuilder.buildErrorResponse(e.getErrCode(), e.getMessage());
        } catch (Exception e) {
            log.error("新建版本未知异常", e);
            return ResponseEntityBuilder.buildErrorResponse(ErrorCodeEnum.SERVER_ERROR);
        } finally {
            lock.unlock();
        }

    }

    @ApiOperation(value = "决策树_锁定版本")
    @PostMapping(value = "/lockDecisionTree/{versionId}")
    @ArchivesLog(type = OperateTypeEnum.UPDATE,name = OperateNameConst.ComponentOpt.LOCK_VERSION)
    public ResponseEntityDto<String> lockDecisionTree(@PathVariable Long versionId) {
        versionService.lockDecisionTree(versionId);
        return ResponseEntityBuilder.buildNormalResponse("锁定规则及版本成功!");
    }

    @ApiOperation(value = "决策树_查看版本列表")
    @PostMapping(value = "/listByDecisionTreeCode")
    public ResponseEntityDto<PageResult<List<DecisionTreeVersionListVo>, DecisionTreeVersion>> listByDecisionTreeCode(@Valid @RequestBody AssemblyRuleCodeReq req) {
        return versionService.listByDecisionTreeCode(req);
    }
}
